package com.aote.util.shuMa;

import org.apache.log4j.Logger;
import org.json.JSONObject;

import java.math.BigDecimal;

public class ShuMa {
    private static Logger logger = Logger.getLogger(ShuMa.class);

    public int CheckGasCard(short com, int baud) {
        return -1;
    }

    public int FormatGasCard(short com, int baud, String kmm, String kh, String dqdm) {
        return -1;
    }

    /**
     * C#中原有的入参为
     * short com, int baud, ref string kmm, string kh, string dqdm,
     * int ql, int csql, int ccsql, short cs, int ljgql, int bjql,
     * int czsx, int tzed, string sqrq, string cssqrq, int oldprice,
     * int newprice, string sxrq, string sxbj
     * 其中只用到了现有的四个值
     * 并且ref特性无法实现，所以返回值从int更改为json
     * json中有两个值
     * ret:C#中该方法的int返回值
     * result:C#中被ref修饰的kmm值
     * @param kh 卡号
     * @param ql 购买气量
     * @param cs 购买次数
     */
    public JSONObject WriteGasCard(String kmm, String kh, int ql, int cs) {
        int ret = 1;
        short cs2 = cheackNumberIsMaxValue(cs);
        try {
            logger.debug("sell gas start:" + "--kh--" + kh + "--ql--" + ql + "--cs--" + cs2);
            String result = (Encrypt(Integer.parseInt(kh), (cs2) * 1000 + ql) + "");//.PadLeft(8, '0');
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < 8 - result.length(); i++) {
                sb.append(0);
            }
            result += sb.toString();
            kmm = result;
            if (result.equals(null)) {
                ret = -1;
            } else {
                ret = 0;
            }
        } catch (Exception e) {
            logger.debug("sell gas exption is:" + e.getMessage() + e.getStackTrace());
        }
        JSONObject jo = new JSONObject();
        jo.put("ret", ret);
        jo.put("result", kmm);
        return jo;
    }


    private static int Encrypt(int intMkey, int intOriginal) {
        int[] array = new int[10];
        int[] array2 = new int[10];
        short[] array3 = new short[7];
        short[] array4 = new short[7];
        short[] array5 = new short[7];
        short[] array6 = new short[12];
        int result;
        try {
            array3[0] = cheackNumberIsMaxValue(intMkey / 4096);
            array4[0] = cheackNumberIsMaxValue(intMkey % 4096);
            array5[0] = 0;
            int num = 1;
            do {
                array5[num] = cheackNumberIsMaxValue(array3[num - 1]);
                array3[num] = cheackNumberIsMaxValue(array4[num - 1]);
                array4[num] = cheackNumberIsMaxValue(SecretKey((int) array3[num - 1], (int) (array4[num - 1] ^ array5[num - 1])));
                array6[2 * num - 2] = cheackNumberIsMaxValue(array4[num] % 64);
                array6[2 * num - 1] = cheackNumberIsMaxValue(array4[num] / 64);
                num++;
            } while (num <= 6);
            array[0] = cheackNumberIsMaxValue(intOriginal / 4096);
            array2[0] = cheackNumberIsMaxValue(intOriginal % 4096);
            array[1] = cheackNumberIsMaxValue(array[0] ^ cheackNumberIsMaxValue(array6[4] * 64 + array6[5]));
            array2[1] = cheackNumberIsMaxValue(array2[0] ^ cheackNumberIsMaxValue(array6[6] * 64 + array6[7]));
            array[2] = array[1];
            array2[2] = cheackNumberIsMaxValue(array2[1] ^ array[1]);
            num = 3;
            do {
                array[num] = array2[num - 1];
                array2[num] = cheackNumberIsMaxValue(array[num - 1] ^ cheackNumberIsMaxValue(ftnEncrypt(array2[num - 1], (int) array6[num - 3])));
                num++;
            }
            while (num <= 6);
            array2[7] = array2[6];
            array[7] = cheackNumberIsMaxValue(array[6] ^ array2[6]);
            array2[8] = cheackNumberIsMaxValue(array2[7] ^ cheackNumberIsMaxValue(array6[8] * 64 + array6[9]));
            array[8] = cheackNumberIsMaxValue(array[7] ^ cheackNumberIsMaxValue(array6[10] * 64 + array6[11]));
            int num2 = 525252;
            array2[9] = cheackNumberIsMaxValue(array2[8] ^ num2 / 4096);
            array[9] = cheackNumberIsMaxValue(array[8] ^ num2 % 4096);
            result = array[9] * 4096 + array2[9];
        } catch (Exception e) {
            result = 0;
        }
        return result;
    }

    private static int ftnEncrypt(int intX1, int intX2) {
        short[] array = new short[4];
        short[] array2 = new short[3];
        short[] array3 = new short[4];
        array[3] = cheackNumberIsMaxValue(intX1 % 8);
        intX1 /= 8;
        array[2] = cheackNumberIsMaxValue(intX1 % 8);
        intX1 /= 8;
        array[1] = cheackNumberIsMaxValue(intX1 % 8);
        intX1 /= 8;
        array[0] = cheackNumberIsMaxValue(intX1 % 8);
        intX1 /= 8;
        array2[1] = cheackNumberIsMaxValue(intX2 % 8);
        intX2 /= 8;
        array2[0] = cheackNumberIsMaxValue(intX2 % 8);
        intX2 /= 8;
        short intX3 = cheackNumberIsMaxValue(array[1] ^ array2[0] ^ array[0]);
        short num = cheackNumberIsMaxValue(array[2] ^ array2[1] ^ array[3]);
        array3[1] = Movs3(intX3, num, (short) 1);
        array3[2] = Movs3(num, array3[1], (short) 0);
        array3[3] = Movs3(array[3], array3[1], (short) 1);
        array3[0] = Movs3(array[0], array3[1], (short) 0);
        return new BigDecimal(
                (double) array3[0] * 512.0 + (double) array3[1] * 64.0 + (double) array3[2] * 8.0 + (double) array3[3]
        ).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
    }

    private static int SecretKey(int intA, int intB) {
        short num = cheackNumberIsMaxValue(intA % 8);
        intA /= 8;
        short num2 = cheackNumberIsMaxValue(intA % 8);
        intA /= 8;
        short num3 = cheackNumberIsMaxValue(intA % 8);
        intA /= 8;
        short num4 = cheackNumberIsMaxValue(intA % 8);
        intA /= 8;
        short num5 = cheackNumberIsMaxValue(intB % 8);
        intB /= 8;
        short num6 = cheackNumberIsMaxValue(intB % 8);
        intB /= 8;
        short num7 = cheackNumberIsMaxValue(intB % 8);
        intB /= 8;
        short num8 = cheackNumberIsMaxValue(intB % 8);
        intB /= 8;
        short intX = cheackNumberIsMaxValue(num3 ^ num4);
        short num9 = cheackNumberIsMaxValue(num ^ num2);
        short num10 = Movs3(intX, cheackNumberIsMaxValue(num9 ^ num8), (short) 1);
        short num11 = Movs3(num9, cheackNumberIsMaxValue(num10 ^ num7), (short) 0);
        short num12 = Movs3(num4, cheackNumberIsMaxValue(num10 ^ num6), (short) 0);
        short num13 = Movs3(num, cheackNumberIsMaxValue(num11 ^ num5), (short) 1);
        return new BigDecimal(
                (double) num12 * 512.0 + (double) num10 * 64.0 + (double) num11 * 8.0 + (double) num13
        ).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
    }

    private static short Movs3(short intX1, short intX2, short intX3) {
        short num = (short) ((intX1 + intX2 + intX3) % 8);
        short num2 = cheackNumberIsMaxValue(num / 2 + num % 2 * 4);
        return cheackNumberIsMaxValue(num2 / 2 + num2 % 2 * 4);
    }

    /**
     * 数据溢出检查
     */
    private static short cheackNumberIsMaxValue(long num) {
        if (num > Short.MAX_VALUE || num < Short.MIN_VALUE) {
            throw new RuntimeException("算数运算导致数据溢出！");
        }
        return (short) num;
    }
}
